﻿// MIT License
// 开源地址：https://gitee.com/co1024/AbcMvc
// Copyright (c) 2021-2022 1024
// Abc.Mvc=Furion+EF+SqlSugar+Pear layui admin.

namespace Abc.Core;
/// <summary>
/// sqlsugar扩展方法
/// </summary>
public static class SqlSugarExtensions
{
    /// <summary>
    /// 更新忽略的字段
    /// </summary>
    private static readonly string[] UpdateIgnoreColumns = new string[] { "CreatorUserId", "CreatorUserName", "CreationTime" };

    #region Method
    /// <summary>
    /// 根据ID查询一条数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="_db"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public static T GetById<T>(this ISqlSugarClient _db, dynamic id)
    {
        return _db.Queryable<T>().InSingle(id);
    }
    /// <summary>
    /// 获取全部数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="_db"></param>
    /// <returns></returns>
    public static List<T> GetList<T>(this ISqlSugarClient _db)
    {
        return _db.Queryable<T>().ToList();
    }
    /// <summary>
    /// 获取列表
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="_db"></param>
    /// <param name="whereExpression">条件表达式</param>
    /// <returns></returns>
    public static List<T> GetList<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression)
    {
        return _db.Queryable<T>().Where(whereExpression).ToList();
    }
    /// <summary>
    /// 获取单条数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="_db"></param>
    /// <param name="whereExpression">条件表达式</param>
    /// <returns></returns>
    public static T GetSingle<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression)
    {
        return _db.Queryable<T>().Single(whereExpression);
    }
    /// <summary>
    /// 获取第一条数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="_db"></param>
    /// <param name="whereExpression">条件表达式</param>
    /// <returns></returns>
    public static T GetFirst<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression)
    {
        return _db.Queryable<T>().First(whereExpression);
    }
    /// <summary>
    /// 查询分页数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="_db"></param>
    /// <param name="whereExpression">条件表达式</param>
    /// <param name="page">分页数据</param>
    /// <returns></returns>
    public static List<T> GetPageList<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression, PageModel page)
    {
        int count = 0;
        var result = _db.Queryable<T>().Where(whereExpression).ToPageList(page.PageIndex, page.PageSize, ref count);
        page.TotalCount = count;
        return result;
    }
    /// <summary>
    /// 查询分页数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="_db"></param>
    /// <param name="whereExpression">条件表达式</param>
    /// <param name="page">分页数据</param>
    /// <param name="orderByExpression">排序表达式</param>
    /// <param name="orderByType">排序方式，默认正序</param>
    /// <returns></returns>
    public static List<T> GetPageList<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
    {
        int count = 0;
        var result = _db.Queryable<T>().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToPageList(page.PageIndex, page.PageSize, ref count);
        page.TotalCount = count;
        return result;
    }
    public static List<T> GetPageList<T>(this ISqlSugarClient _db, List<IConditionalModel> conditionalList, PageModel page)
    {
        int count = 0;
        var result = _db.Queryable<T>().Where(conditionalList).ToPageList(page.PageIndex, page.PageSize, ref count);
        page.TotalCount = count;
        return result;
    }
    public static List<T> GetPageList<T>(this ISqlSugarClient _db, List<IConditionalModel> conditionalList, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
    {
        int count = 0;
        var result = _db.Queryable<T>().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(conditionalList).ToPageList(page.PageIndex, page.PageSize, ref count);
        page.TotalCount = count;
        return result;
    }
    public static bool IsAny<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression)
    {
        return _db.Queryable<T>().Where(whereExpression).Any();
    }
    public static int Count<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression)
    {

        return _db.Queryable<T>().Where(whereExpression).Count();
    }

    public static bool Insert<T>(this ISqlSugarClient _db, T insertObj) where T : class, new()
    {
        return _db.Insertable(insertObj).ExecuteCommand() > 0;
    }

    public static bool InsertOrUpdate<T>(this ISqlSugarClient _db, T data) where T : class, new()
    {
        return _db.Storageable(data).ExecuteCommand() > 0;
    }
    public static bool InsertOrUpdate<T>(this ISqlSugarClient _db, List<T> datas) where T : class, new()
    {
        return _db.Storageable(datas).ExecuteCommand() > 0;
    }

    public static int InsertReturnIdentity<T>(this ISqlSugarClient _db, T insertObj) where T : class, new()
    {
        return _db.Insertable(insertObj).ExecuteReturnIdentity();
    }
    public static long InsertReturnBigIdentity<T>(this ISqlSugarClient _db, T insertObj) where T : class, new()
    {
        return _db.Insertable(insertObj).ExecuteReturnBigIdentity();
    }
    public static long InsertReturnSnowflakeId<T>(this ISqlSugarClient _db, T insertObj) where T : class, new()
    {
        return _db.Insertable(insertObj).ExecuteReturnSnowflakeId();
    }
    public static List<long> InsertReturnSnowflakeId<T>(this ISqlSugarClient _db, List<T> insertObjs) where T : class, new()
    {
        return _db.Insertable(insertObjs).ExecuteReturnSnowflakeIdList();
    }
    public static Task<long> InsertReturnSnowflakeIdAsync<T>(this ISqlSugarClient _db, T insertObj) where T : class, new()
    {
        return _db.Insertable(insertObj).ExecuteReturnSnowflakeIdAsync();
    }
    public static Task<List<long>> InsertReturnSnowflakeIdAsync<T>(this ISqlSugarClient _db, List<T> insertObjs) where T : class, new()
    {
        return _db.Insertable(insertObjs).ExecuteReturnSnowflakeIdListAsync();
    }

    public static T InsertReturnEntity<T>(this ISqlSugarClient _db, T insertObj) where T : class, new()
    {
        return _db.Insertable(insertObj).ExecuteReturnEntity();
    }

    public static bool Insert<T>(this ISqlSugarClient _db, T[] insertObjs) where T : class, new()
    {
        return _db.Insertable(insertObjs).ExecuteCommand() > 0;
    }
    public static bool Insert<T>(this ISqlSugarClient _db, List<T> insertObjs) where T : class, new()
    {
        return _db.Insertable(insertObjs).ExecuteCommand() > 0;
    }
    public static bool Update<T>(this ISqlSugarClient _db, T updateObj) where T : class, new()
    {
        return _db.Updateable(updateObj).IgnoreColumns(UpdateIgnoreColumns).ExecuteCommand() > 0;
    }
    public static bool Update<T>(this ISqlSugarClient _db, T[] updateObjs) where T : class, new()
    {
        return _db.Updateable(updateObjs).IgnoreColumns(UpdateIgnoreColumns).ExecuteCommand() > 0;
    }
    public static bool Update<T>(this ISqlSugarClient _db, List<T> updateObjs) where T : class, new()
    {
        return _db.Updateable(updateObjs).IgnoreColumns(UpdateIgnoreColumns).ExecuteCommand() > 0;
    }
    public static bool Update<T>(this ISqlSugarClient _db, Expression<Func<T, T>> columns, Expression<Func<T, bool>> whereExpression) where T : class, new()
    {
        return _db.Updateable<T>().SetColumns(columns).Where(whereExpression).ExecuteCommand() > 0;
    }
    public static bool UpdateSetColumnsTrue<T>(this ISqlSugarClient _db, Expression<Func<T, T>> columns, Expression<Func<T, bool>> whereExpression) where T : class, new()
    {
        return _db.Updateable<T>().SetColumns(columns, true).Where(whereExpression).ExecuteCommand() > 0;
    }
    public static bool Delete<T>(this ISqlSugarClient _db, T deleteObj) where T : class, new()
    {
        return _db.Deleteable<T>().Where(deleteObj).ExecuteCommand() > 0;
    }
    public static bool Delete<T>(this ISqlSugarClient _db, List<T> deleteObjs) where T : class, new()
    {
        return _db.Deleteable<T>().Where(deleteObjs).ExecuteCommand() > 0;
    }
    public static bool Delete<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression) where T : class, new()
    {
        return _db.Deleteable<T>().Where(whereExpression).ExecuteCommand() > 0;
    }
    public static bool DeleteById<T>(this ISqlSugarClient _db, dynamic id) where T : class, new()
    {
        return _db.Deleteable<T>().In(id).ExecuteCommand() > 0;
    }
    public static bool DeleteByIds<T>(this ISqlSugarClient _db, dynamic[] ids) where T : class, new()
    {
        return _db.Deleteable<T>().In(ids).ExecuteCommand() > 0;
    }
    #endregion

    #region Async Method
    public static Task<T> GetByIdAsync<T>(this ISqlSugarClient _db, dynamic id)
    {
        return _db.Queryable<T>().InSingleAsync(id);
    }
    public static Task<List<T>> GetListAsync<T>(this ISqlSugarClient _db)
    {
        return _db.Queryable<T>().ToListAsync();
    }

    public static Task<List<T>> GetListAsync<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression)
    {
        return _db.Queryable<T>().Where(whereExpression).ToListAsync();
    }
    public static Task<T> GetSingleAsync<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression)
    {
        return _db.Queryable<T>().SingleAsync(whereExpression);
    }
    public static Task<T> GetFirstAsync<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression)
    {
        return _db.Queryable<T>().FirstAsync(whereExpression);
    }
    public static async Task<List<T>> GetPageListAsync<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression, PageModel page)
    {
        RefAsync<int> count = 0;
        var result = await _db.Queryable<T>().Where(whereExpression).ToPageListAsync(page.PageIndex, page.PageSize, count);
        page.TotalCount = count;
        return result;
    }
    public static async Task<List<T>> GetPageListAsync<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
    {
        RefAsync<int> count = 0;
        var result = await _db.Queryable<T>().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(whereExpression).ToPageListAsync(page.PageIndex, page.PageSize, count);
        page.TotalCount = count;
        return result;
    }
    public static async Task<List<T>> GetPageListAsync<T>(this ISqlSugarClient _db, List<IConditionalModel> conditionalList, PageModel page)
    {
        RefAsync<int> count = 0;
        var result = await _db.Queryable<T>().Where(conditionalList).ToPageListAsync(page.PageIndex, page.PageSize, count);
        page.TotalCount = count;
        return result;
    }
    public static async Task<List<T>> GetPageListAsync<T>(this ISqlSugarClient _db, List<IConditionalModel> conditionalList, PageModel page, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
    {
        RefAsync<int> count = 0;
        var result = await _db.Queryable<T>().OrderByIF(orderByExpression != null, orderByExpression, orderByType).Where(conditionalList).ToPageListAsync(page.PageIndex, page.PageSize, count);
        page.TotalCount = count;
        return result;
    }
    public static Task<bool> IsAnyAsync<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression)
    {
        return _db.Queryable<T>().Where(whereExpression).AnyAsync();
    }
    public static Task<int> CountAsync<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression)
    {

        return _db.Queryable<T>().Where(whereExpression).CountAsync();
    }

    public static async Task<bool> InsertOrUpdateAsync<T>(this ISqlSugarClient _db, T data) where T : class, new()
    {
        return await _db.Storageable(data).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> InsertOrUpdateAsync<T>(this ISqlSugarClient _db, List<T> datas) where T : class, new()
    {
        return await _db.Storageable(datas).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> InsertAsync<T>(this ISqlSugarClient _db, T insertObj) where T : class, new()
    {
        return await _db.Insertable(insertObj).ExecuteCommandAsync() > 0;
    }
    public static Task<int> InsertReturnIdentityAsync<T>(this ISqlSugarClient _db, T insertObj) where T : class, new()
    {
        return _db.Insertable(insertObj).ExecuteReturnIdentityAsync();
    }
    public static Task<long> InsertReturnBigIdentityAsync<T>(this ISqlSugarClient _db, T insertObj) where T : class, new()
    {
        return _db.Insertable(insertObj).ExecuteReturnBigIdentityAsync();
    }
    public static async Task<T> InsertReturnEntityAsync<T>(this ISqlSugarClient _db, T insertObj) where T : class, new()
    {
        return await _db.Insertable(insertObj).ExecuteReturnEntityAsync();
    }
    public static async Task<bool> InsertAsync<T>(this ISqlSugarClient _db, T[] insertObjs) where T : class, new()
    {
        return await _db.Insertable(insertObjs).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> InsertAsync<T>(this ISqlSugarClient _db, List<T> insertObjs) where T : class, new()
    {
        return await _db.Insertable(insertObjs).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> UpdateAsync<T>(this ISqlSugarClient _db, T updateObj) where T : class, new()
    {
        return await _db.Updateable(updateObj).IgnoreColumns(UpdateIgnoreColumns).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> UpdateAsync<T>(this ISqlSugarClient _db, T[] updateObjs) where T : class, new()
    {
        return await _db.Updateable(updateObjs).IgnoreColumns(UpdateIgnoreColumns).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> UpdateAsync<T>(this ISqlSugarClient _db, List<T> updateObjs) where T : class, new()
    {
        return await _db.Updateable(updateObjs).IgnoreColumns(UpdateIgnoreColumns).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> UpdateAsync<T>(this ISqlSugarClient _db, Expression<Func<T, T>> columns, Expression<Func<T, bool>> whereExpression) where T : class, new()
    {
        return await _db.Updateable<T>().SetColumns(columns).Where(whereExpression).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> UpdateSetColumnsTrueAsync<T>(this ISqlSugarClient _db, Expression<Func<T, T>> columns, Expression<Func<T, bool>> whereExpression) where T : class, new()
    {
        return await _db.Updateable<T>().SetColumns(columns, true).Where(whereExpression).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> DeleteAsync<T>(this ISqlSugarClient _db, T deleteObj) where T : class, new()
    {
        return await _db.Deleteable<T>().Where(deleteObj).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> DeleteAsync<T>(this ISqlSugarClient _db, List<T> deleteObjs) where T : class, new()
    {
        return await _db.Deleteable<T>().Where(deleteObjs).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> DeleteAsync<T>(this ISqlSugarClient _db, Expression<Func<T, bool>> whereExpression) where T : class, new()
    {
        return await _db.Deleteable<T>().Where(whereExpression).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> DeleteByIdAsync<T>(this ISqlSugarClient _db, dynamic id) where T : class, new()
    {
        return await _db.Deleteable<T>().In(id).ExecuteCommandAsync() > 0;
    }
    public static async Task<bool> DeleteByIdsAsync<T>(this ISqlSugarClient _db, dynamic[] ids) where T : class, new()
    {
        return await _db.Deleteable<T>().In(ids).ExecuteCommandAsync() > 0;
    }
    #endregion







    #region 删除

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="ids">id字符串，英文逗号隔开</param>
    /// <returns></returns>
    public static bool DeleteByIds<T>(this ISqlSugarClient _db, string ids) where T : class, new()
    {
        var objs = ids.ToSplitObjects();
        return _db.Deleteable<T>().In(objs).ExecuteCommand() > 0;
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="ids">id字符串，英文逗号隔开</param>
    /// <returns></returns>
    public static async Task<bool> DeleteByIdsAsync<T>(this ISqlSugarClient _db, string ids) where T : class, new()
    {
        var objs = ids.ToSplitObjects();
        return await _db.Deleteable<T>().In(objs).ExecuteCommandAsync() > 0;
    }

    #endregion 删除

    #region 假删除
    /// <summary>
    /// 假删除
    /// </summary>
    /// <typeparam name="T">实体</typeparam>
    /// <param name="_db"></param>
    /// <param name="ids">删除的id字符串，英文逗号隔开</param>
    /// <returns></returns>
    public static bool FakeDelete<T>(this ISqlSugarClient _db, string ids) where T : class, new()
    {
        var objs = ids.ToSplitObjects();
        return _db.Deleteable<T>().In(objs)
            .IsLogic()
            .ExecuteCommand("IsDeleted", DateTimeOffset.Now, "DeletedTime", "DeletedUserName", App.HttpContext.GetLoginUserAccount()) > 0;
    }
    /// <summary>
    /// 假删除
    /// </summary>
    /// <typeparam name="T">实体</typeparam>
    /// <param name="_db"></param>
    /// <param name="ids">删除的id字符串，英文逗号隔开</param>
    /// <returns></returns>
    public static async Task<bool> FakeDeleteAsync<T>(this ISqlSugarClient _db, string ids) where T : class, new()
    {
        var objs = ids.ToSplitObjects();
        return await _db.Deleteable<T>().In(objs)
             .IsLogic()
             .ExecuteCommandAsync("IsDeleted", DateTimeOffset.Now, "DeletedTime", "DeletedUserName", App.HttpContext.GetLoginUserAccount()) > 0;
    }
    #endregion
}
